<?php

namespace brand\logic;
use app\common\model\Area;
use brand\build\Columns;
use brand\tools\Functions;
use think\facade\Db;
use think\facade\Env;

class BrandHelper
{
    /**
     * 格式化options参数
     *
     * @param array  $options
     * @param string $labelName value名称
     * @param string $valueName key名称
     *
     * @return array
     */
    public static function formatOptions(array $options, $labelName = 'label', $valueName = 'value'): array
    {
        $data = [];
        foreach ($options as $k => $v) {
            array_push($data, [$labelName => $v, $valueName => (string)$k]);
        }
        return $data;
    }

    public static function encodeOptions(array $options, $labelName = 'label', $valueName = 'value'): array
    {
        $data = [];
        foreach ($options as  $v) {
            $value = $v[$labelName];
            if ($value == 'true') $value = true;
            elseif ($value == 'false') $value = false;
            $data[$v[$valueName]] = $value;
        }
        return $data;
    }

    public static function optionsStrToInt($params)
    {
        if (!$params) $params = [];
        foreach ($params as $key => $param) {
            if (is_numeric($param['value'])) {
                $params[$key]['value']= (int)$param['value'];
            }
        }
        return $params;
    }





    public static function getCurdConfigByName($name , $type = ASSERT_ACTIVE)
    {
        $name = self::addonTableName($name,Config::$addon_name);
        $file = root_path() . Config::$curd_path . $name . Config::CURD_SUFFIX;
        //文件是否存在
        if (file_exists($file) ){
            $curd = json_decode(file_get_contents($file),1);
        }else{
            $curd = [];
        }
        return $curd;
    }

    public static function getCurdTablesPath()
    {

        self::IsDir(Config::$curd_path,1);
        return root_path() . Config::$curd_path;
    }


    /**
     * 通过Curd名称获取主键
     * @param $name
     * @return mixed|string
     */
    public static function getPkByName($name)
    {
        $conf = self::getCurdConfigByName($name);
        $pk = $conf['page']['pk'] ?? ( $conf['controller']['pk'] ?? '' );
        if (!$pk) {
            $pk = Database::getPkByTable(self::getTableNameByName($name));
        }
        return $pk;
    }

    /**
     * 通过Curd名称获取表名称
     * @param $name
     * @return mixed
     */
    public static function getTableNameByName($name)
    {
        $conf = self::getCurdConfigByName($name);
        return $conf['page']['table'] ?? $name;
    }

    /**
     * 通过Curd名称获取表字段
     * @param $name
     * @return array
     */
    public static function getTableFieldByName($name)
    {
        $table = self::getTableNameByName($name);
        return Database::getTableFields($table);
    }

    public static function getMixin($name)
    {
        $file = Config::getMixinPath($name);
        if (!file_exists($file)) return  "";
        return file_get_contents($file);
    }



    /**
     * 字段过滤
     */
    public static function submitCharField($curdName)
    {
        $params = request()->param();
        $conf = self::getCurdConfigByName($curdName);
        if (!$conf) return $params;

        $columns = $conf['columns'];
        $pk = $conf['controller']['pk'] ?? 'id';

        //过滤掉主键
        if (isset($params[$pk]) && !$params[$pk]) unset($params[$pk]);

        foreach ($columns as $field => $column) {

            $update_time = $column['form']['update_time'] ?? "";
            //更新自动写入
            if ($update_time && !isset($params[$field])){
                $params[$field] = $update_time == 'timestamp' ? time() : date('Y-m-d H:i:s',time());
            }
            //新增自动写入
            $create_time = $column['form']['create_time'] ?? "";
            if ($create_time && !isset($params[$field]) && (!isset($params[$pk]) || !$params[$pk])){
                $params[$field] = $create_time == 'timestamp' ? time() : date('Y-m-d H:i:s',time());
            }
        }



        foreach ($params as $key => $param) {
            $data_type = $columns[$key] ?? [];
            $method = $data_type['form']['method'] ?? 'input';
            $ClassName = Config::BRAND_NAMESPACE . Functions::toCamelCase($method);

            if (class_exists($ClassName)){

                $ClassObject = new $ClassName($data_type,[]);
                $params[$key] = $ClassObject->checkUpdateData($key,$param);
            }
        }

        foreach ($columns as $key => $column) {
            //省市区
            if (isset($column['special_action']) && $column['special_action'] == 'area'){

                $cascader = $column['form']['cascader'] ?? [];
                $areas = $params[$key];
                if (isset($cascader['province']) && isset($areas[0])) $params[$cascader['province']] = $areas[0];
                if (isset($cascader['city']) && isset($areas[1])) $params[$cascader['city']] = $areas[1];
                if (isset($cascader['area']) && isset($areas[2])) $params[$cascader['area']] = $areas[2];
            }

        }

        return $params;
    }

    public static function buildParams($pk,$curdName,$columns)
    {

        $params = request()->param();

        $pk = $pk ?: BrandHelper::getPkByName($curdName);

        $limit = $params['limit'] ?? Config::$page_limit;
        $sort_field = $params['sort_field'] ?? $pk;
        $sort_order = $params['sort_order'] ?? 'desc';


        $where = [];
        foreach ($params as $key => $param) {

            if ($param === "") continue;
            if (in_array($key,['page','limit','sort_field','sort_order'])) continue;

            $column = $columns[$key] ?? [];
            if (!$column) continue;

            $method = $column['form']['method'] ?? 'input';
            $ClassName = Config::BRAND_NAMESPACE . Functions::toCamelCase($method);

            if (!class_exists($ClassName)) continue;

            $ClassObject = new $ClassName($column,[]);
            $ClassObject->field = $curdName;

            $condition = $ClassObject->buildCondition($key,$param);

            if (!$condition) continue;
            $where[] = $condition;
        }

        return [$where,$limit,$sort_field,$sort_order];
    }

    public static function arraySplice($array, $find_field, $field,$item)
    {
        $res = [];
        foreach ($array as $key => $value) {
            $res[$key] = $value;
            if ($key == $find_field){
                $res[$field] = $item;
            }
        }
        return $res;
    }



    public static function SoftDelete($columns)
    {
        $soft_delete = [];
        foreach ($columns as $field => $column) {
            $delete_time = $column['form']['delete_time'] ?? "";
            if ($delete_time){
                $soft_delete[$field] = $delete_time == 'timestamp' ? time() : date('Y-m-d H:i:s',time());
            }
        }
        return $soft_delete;

    }

    public static function getCurdNameByControllerName($controller = '')
    {
        $controller = str_replace('.','_',($controller ?: request()->controller()));
        return Functions::toUnderScore( $controller );
    }

    public static function checkCurdName($curdName,$return = 0)
    {
        if (in_array(Functions::toCamelCase($curdName), Config::NO_CURD_CONTROLLER)){
            return false;
        }
        if (!self::getCurdConfigByName($curdName) && !Columns::getConfig()){
            if ($return) return false;
            exit('CURD配置文件不存在，不需CURD请在控制器里重写方法。如需CURD请先配置CURD信息。');
        }

        return true;
    }

    /**
     * 文件是否存在
     * @param $file
     * @return bool
     */
    public static function FileExistsException($file)
    {
        return  file_exists(root_path().$file) ;
    }

    /**
     * 获取命名空间和类名称
     * @param $path
     * @return string[]
     */
    public static function pathInfo($path)
    {

        $pathArr = explode('/',$path);
        $nameSpace = "";
        $className = "";
        foreach ($pathArr as $key => $item) {
            if ($key < count($pathArr)-1){
                if ($nameSpace){
                    $nameSpace .= '\\' . $item ;
                }else{
                    $nameSpace = $item;
                }
            }else{
                $className = str_replace('.php','',$item);
            }
        }
        return ['namespace' => $nameSpace,'className'=>$className];


    }

    /**
     * 文件夹是否存在
     * @param $dir
     * @param int $error
     * @return bool
     * @throws \Exception
     */
    public static function IsDir($dir ,$mkdir = 0)
    {
        $dir = root_path().$dir;
        $is_dir =  is_dir($dir);
        if ($mkdir && !$is_dir){
            //创建文件夹
            mkdir($dir,0777,true);
            return $dir;
        }
        return $is_dir;
    }

    /**
     * 数组转字符串
     * @param $array
     * @param $division
     * @return mixed|string
     */
    public static function array2String($array, $division = '')
    {
        if (!is_array($array)) return $array;
        $division = $division ?: Config::ARRAY_DIVISION;
        return implode($division , $array);
    }

    /**
     * 字符串转数组
     * @param $string
     * @param $division
     * @return array|false|string[]
     */
    public static function string2array($string, $division = '' )
    {
        if (is_array($string) || !$string) return $string;
        $division = $division ?: Config::ARRAY_DIVISION;
        return array_filter(explode($division , $string));
    }

    public static function arrayFindInArray($array,$options,$division = '')
    {
        $division = $division ?: Config::ARRAY_DIVISION;
        $value = "";
        if (!is_array($array) || !$array) return $array;
        foreach ($array as $index => $_value) {
            if ($index != 0){
                $value .= $division;
            }
            $value .= ($options[$_value] ?? "");
        }
        return $value;
    }

    public static function value2time($value , $ms = 1000)
    {
        is_numeric($value)
            ? $value = (int)ceil($value * $ms)
            : $value = strtotime($value) * $ms;

        return $value;
    }

    public static function time2value($time)
    {
        if ($time && is_numeric($time)) $time = date('Y-m-d H:i:s',$time);
        return $time;
    }

    /**
     * 毫秒转秒
     * @param $ms
     */
    public static function ms2time($ms)
    {
        if (is_numeric($ms) && strlen((string)$ms) > 10) $ms = (int)ceil($ms/1000);
        return $ms;
    }

    public static function cityOptions($level = 3)
    {

        $areas = Area::cache()->name('area')->field('id as value,name as label')->where('pid',0)->select();
        if ($level >= 2){
            foreach ($areas as $key => $province) {
                $cities = Area::cache()->name('area')->field('id as value,name as label')->where('pid',$province['value'])->select()->toArray();

                if ($level >= 3){
                    foreach ($cities as $index => $city) {
                        $cities[$index]['children'] = Area::cache()->name('area')->field('id as value,name as label')->where('pid',$city['value'])->select()->toArray();
                    }
                }

                $province['children'] = $cities;

                $areas[$key] = $province;
            }
        }
        return $areas->toArray();
    }

    public static function columnsInsertArray($columns, $find_key, $array ,$seat = 'down')
    {
        if (!$array) return $columns;
        $columns_arr = [];
        foreach ($array as $key => $item) {
            if (isset($columns[$key])) unset($columns[$key]);
        }
        if ($find_key == '__ba__top'){
            $columns_arr = array_merge($array , $columns);
        }else{
            foreach ($columns as $key => $column) {
                if ($seat == 'down') $columns_arr[$key] = $column;
                if ($find_key == $key) {

                    $columns_arr = array_merge($columns_arr , $array);
                }
                if ($seat != 'down') $columns_arr[$key] = $column;
            }
        }

        return $columns_arr;
    }


    public static function getUrlPathInfo($url,$get = [])
    {
        $path = '/'.request()->root();
        if (Config::$addon_name){
            $path = '/'.request()->pathinfo();
        }
        return url($path.'/'.$url,$get);
    }

    public static function getAdminName()
    {
        $admin = 'admin';
        $config = config('app');
        if (isset($config['app_map']) && $config['app_map']){
            foreach ($config['app_map'] as $key => $item) {
                if ($item == $admin){
                    $admin = $key;
                    break;
                }
            }
        }
        return $admin;
    }

    /**
     * 插件表
     * @param $tableList
     * @param $addon
     */
    public static function addonTables($tableList, $addon)
    {
        $addon_info = get_addon_info($addon);
        if (!$addon_info || !isset($addon_info['table_prefix']) || !$addon_info['table_prefix']) return $tableList;

        foreach ($tableList as $key => $item) {
            if (strrpos($item['table'],$addon_info['table_prefix']) !== 0){
                unset($tableList[$key]);
            }else{
                $curdPath = self::getCurdTablesPath() . self::addonTableName($item['table'],$addon) . Config::CURD_SUFFIX;
                $tableList[$key]['is_curd'] = file_exists($curdPath) ? 1 : 0;
            }
        }
        $tableList = array_values($tableList);
        return $tableList;

    }

    /**
     * 插件表名称
     * @param $table
     * @param $addon
     */
    public static function addonTableName($table, $addon = null)
    {
        if (!$addon) $addon = Config::$addon_name;
        $addon_info = get_addon_info($addon);
        if (!$addon_info || !isset($addon_info['table_prefix']) || !$addon_info['table_prefix']){
            return $table;
        }
        return  str_replace($addon_info['table_prefix'],'',$table);
    }

    /**
     * 插件设置curd
     */
    public static function addonBrandTablesPath($addon)
    {

        Config::$curd_path = 'addons/'.$addon.'/brand_tables/';
        Config::$model_path = 'addons/'.$addon.'/common/model/';
        Config::$controller_path = 'addons/'.$addon.'/admin/controller/';
        Config::$validate_path = 'addons/'.$addon.'/common/validate/';
        Config::$addon_name = $addon;
//        self::addonSetPrefix($addon);

    }

    /**
     * 设置插件表前缀
     */
    public static function addonSetPrefix($addon)
    {
        $addon_info = get_addon_info($addon);
        if (isset($addon_info['table_prefix']) && $addon_info['table_prefix']){
            Database::setPrefix($addon_info['table_prefix']);
        }
    }

    /**
     * 反向获取表前缀
     */
    public static function addonGetPrefix($table)
    {

        if (!Config::$addon_name) return $table;
        $addon_info = get_addon_info(Config::$addon_name);
        if (isset($addon_info['table_prefix']) && $addon_info['table_prefix']){
            if (strrpos($table,$addon_info['table_prefix']) === 0){
                return $table;
            }
            return $addon_info['table_prefix'].$table;
        }
        return $table;
    }

    public static function addonInfo()
    {
        if (!Config::$addon_name) return null;
        $res['name'] = Config::$addon_name;
        return $res;
    }

    public static function getOptionList($curl_name,$field)
    {
        $brand = self::getCurdConfigByName($curl_name);
        $value = [];
        foreach ($brand['columns'] as $key => $column) {
            if ($key == $field){
                $_option = $column['form']['options'] ?? [];
                $value = BrandHelper::encodeOptions($_option);
                break;
            }
        }
        return $value;
    }



    





}